fix(l7): reject requests with both CL and TE headers in inference parser (CWE-444)#671
Conversation
|
Self-review follow-up in
|
johntmyers
left a comment
There was a problem hiding this comment.
Thanks for the fix — the guard logic is correct and well-placed, and the tests cover the right cases (header order independence + TE substring rejection).
Two minor items:
-
Whitespace in
te_substring_not_chunkedtest — Theformat!macro's line continuation introduces leading spaces before{body}, so the parsed body ends up as spaces + truncated JSON rather than the intended payload. The test still passes (Content-Length controls read size) but is misleading. Quick fix:let request = format!( "POST /v1/chat/completions HTTP/1.1\r\n\ Host: x\r\n\ Transfer-Encoding: chunkedx\r\n\ Content-Length: {}\r\n\ \r\n{body}", body.len(), );
-
Consider squashing the two commits (guard + capitalization fix) into one before merge.
Also — please run mise run pre-commit before pushing, per AGENTS.md. We need to confirm lint/format/license checks pass locally before we approve workflows to run on this PR.
…ser (CWE-444) The CL/TE desynchronisation guard added in NVIDIA#663 for the REST path was not applied to the inference request parser. A request containing both Content-Length and Transfer-Encoding headers could be interpreted differently by the proxy and the upstream server, enabling HTTP request smuggling (CWE-444, RFC 7230 Section 3.3.3). Add the same rejection check and tests mirroring the REST parser coverage, including TE substring validation. Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
52739de to
f794e25
Compare
|
@johntmyers Thanks for the review! Both items addressed in the squashed commit:
Ran |
Summary
The CL/TE desynchronisation guard added in #663 for the REST path was not applied to the inference request parser. A request containing both
Content-LengthandTransfer-Encodingheaders is silently accepted byinference.rs, withContent-Lengthignored in favour of chunked transfer-encoding. This enables HTTP request smuggling if an upstream server interprets the request viaContent-Lengthinstead (CWE-444, RFC 7230 Section 3.3.3).Related Issue
Closes #670
Follow-up to #663 / #637 — same vulnerability class, sister parser.
Changes
try_parse_http_request()after header parsing loop, returningParseResult::Invalidwhen bothis_chunkedandhas_content_lengthare true.reject_dual_content_length_and_transfer_encodingandreject_dual_transfer_encoding_and_content_lengthtests mirroring SEC-009 coverage inrest.rs.te_substring_not_chunkedtest verifying partial TE tokens likechunkedxare not treated as chunked.rest.rsconvention ("Request contains..."instead of"request contains...").Testing
mise run pre-commitpasses (format, license, lint checks)Executed:
mise run pre-commitlocally:rust:format:check,license:check,python:format:check,helm:lintall passChecklist